package com.bdq.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.bdq.common.constants.Constant;
import com.bdq.common.entity.UserContext;
import com.bdq.common.entity.common.CommonResult;
import com.bdq.common.enums.YesOrNoEnum;
import com.bdq.common.utils.TokenUtil;
import com.bdq.common.utils.UserContextUtil;
import com.bdq.gateway.filter.enums.AuthIgnoreUriEnum;
import com.bdq.gateway.filter.enums.FilterEnum;
import com.bdq.gateway.filter.enums.LocationIgnoreUriEnum;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 全局认证过滤
 *
 * @author malei
 * @date 2023-08-23 15:17
 */
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 认证忽略
        String requestPath = exchange.getRequest().getPath().value();
        List<String> ignoreUriList = Arrays.stream(AuthIgnoreUriEnum.values()).map(AuthIgnoreUriEnum::getUri).collect(Collectors.toList());
        if (ignoreUriList.contains(requestPath)) {
            return chain.filter(exchange);
        }

        // 认证
        String token = exchange.getRequest().getHeaders().getFirst(Constant.HeaderField.token);
        if (StrUtil.isBlank(token)) {
            return filterException(exchange, "请重新登录");
        }
        if (!TokenUtil.vefiry(token)) {
            return filterException(exchange, "请重新登录");
        }

        // 所在地忽略
        List<String> locationIgnoreUriList = Arrays.stream(LocationIgnoreUriEnum.values()).map(LocationIgnoreUriEnum::getUri).collect(Collectors.toList());
        if (locationIgnoreUriList.contains(requestPath)) {
            return chain.filter(exchange);
        }

        // 所在地
        UserContext loginUserContext = UserContextUtil.getLoginUserContext(token);
        if (Objects.isNull(loginUserContext.getUserLocation())) {
            return filterException(exchange, "请填写所在地");
        }

        // 继续执行过滤器链
        return chain.filter(exchange);
    }

    /**
     * 过滤器异常
     *
     * @param exchange
     * @param errorMessage
     * @return
     */
    private Mono<Void> filterException(ServerWebExchange exchange, String errorMessage) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
        String responseJson = String.format("{\"code\":-1,\"msg\":\"%s\"}", errorMessage);
        byte[] bytes = responseJson.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
        return exchange.getResponse().writeWith(Flux.just(buffer));
    }

    @Override
    public int getOrder() {
        // 指定过滤器的执行顺序
        return FilterEnum.AUTH_FILTER.getSort();
    }
}
